package org.wen.soft.generate.model;

import lombok.Data;
import org.wen.soft.asm.model.LoadClass;
import org.wen.soft.asm.model.LoadField;
import org.wen.soft.asm.model.LoadMethod;
import org.wen.soft.generate.util.ExcludeUtil;
import org.wen.soft.generate.util.GStrUtil;
import org.wen.soft.util.PropUtil;
import org.wen.soft.util.StrCastUtil;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.*;

@Data
public class GeneClass {
    LoadClass loadClass;          // ASM获取的类信息
    String modelName = "";        // 模块名称
    String classFileName;         // class文件名称

    // 生成的文件名
    String testFileSimpleName;    // DemoTest 或 DemoChildTest
    String testFileDir;           // c:\doc\org\wen\
    String testFileName;          // c:\doc\org\wen\DemoTest.java

    int modifier;
    String superClassName;

    String packageName;           // com.wen
    String classSimpleName;       // Demo 或 Demo.Child

    String className;             // com.wen.Demo 或 com.wen.Demo$Child
    String classTypeName;         // com.wen.Demo 或 com.wen.Demo.Child

    String varName;               // 变量名称

    Set<String> importList = new HashSet<>();                      // import信息

    List<GeneField> allFields = new ArrayList<>();
    List<GeneField> allTestFields = new ArrayList<>();


    // 方法分类
    List<GeneMethod> allMethods = new ArrayList<>();
    List<GeneMethod> allTestMethods = new ArrayList<>();
    List<GeneMethod> abstractMethods = new ArrayList<>();            // 抽象方法
    List<GeneMethod> finalMethods = new ArrayList<>();               // final方法, 禁止使用代理代理这些方法（根据方法名、参数类型匹配invoke方法）
    List<GeneMethod> constructMethods = new ArrayList<>();           // new User()
    List<GeneMethod> objectMethods = new ArrayList<>();              // user.run()
    List<GeneMethod> classMethods = new ArrayList<>();               // User.run()
    List<GeneMethod> reflectionObjectMethods = new ArrayList<>();    // ReflectionUtils.findMethod(User.class, "setName", String.class)



    boolean thatSpy = false;        // 是否需要SPY代理，如果是final则无法代理、如果方法没有被其他方法调用，则无需进行SPY代理
    boolean thatFinal = false;
    boolean thatAbstract = false;   // 抽象类，构建抽象方法
    boolean thatEnum = false;

    public GeneClass(LoadClass loadClass) {
        this.loadClass = loadClass;
        this.classFileName = loadClass.getFileName();
        this.modelName = PropUtil.getModesNameByClassFile(classFileName);
        this.modifier = loadClass.getAccess();

        this.className = StrCastUtil.pathToClassName(loadClass.getName());
        this.classSimpleName = GStrUtil.simpleName(className);
        this.classTypeName = GStrUtil.classTypeName(className);
        this.packageName = GStrUtil.packageName(className);
        this.superClassName = StrCastUtil.pathToClassName(loadClass.getSuperName());
        this.varName = GStrUtil.varName(classSimpleName);

        this.thatAbstract = Modifier.isAbstract(modifier);
        this.thatFinal = Modifier.isFinal(modifier);

        this.testFileSimpleName = GStrUtil.testFileSimpleName(classSimpleName);
        this.testFileDir = StrCastUtil.pathToPath(PropUtil.getGenerateDir(modelName) + File.separator + StrCastUtil.classNameToPath(packageName) + File.separator);
        this.testFileName =  testFileDir + testFileSimpleName + ".java";

        handlerFields();
        handlerMethods();
    }

    /**
     * 添加字段
     */
    private void handlerFields() {
        for (LoadField loadField : loadClass.getLoadFields()) {
            GeneField geneField = new GeneField(loadField);
            allFields.add(geneField);
            if (!ExcludeUtil.mockFieldExclude(geneField.descriptorClassName)) {
                allTestFields.add(geneField);
            }
        }
    }

    /**
     * 添加方法
     */
    private void handlerMethods() {
        List<LoadMethod> loadMethods = loadClass.getLoadMethods();
        for (int i = 0; i < loadMethods.size(); i++) {
            LoadMethod loadMethod = loadMethods.get(i);
            GeneMethod geneMethod = new GeneMethod(loadMethod, this);
            geneMethod.index = i;
            geneMethod.ownerVarName = varName;
            geneMethod.ownerSimpleName = classSimpleName;
            geneMethod.ownerClassTypeName = classTypeName;
            geneMethod.ownerSupperClassTypeName = superClassName;

            allMethods.add(geneMethod);
            // 构造函数
            if (loadMethod.getName().contains("<init>")) {
                geneMethod.invokeMethod = "new";
                constructMethods.add(geneMethod);
                continue;
            }
            // 其他方法
            int methodModifier = geneMethod.getModifier();
            if (Modifier.isAbstract(methodModifier)) {
                abstractMethods.add(geneMethod);
                continue;
            }
            if (Modifier.isFinal(methodModifier)) {
                finalMethods.add(geneMethod);
            }
            // 互斥
            boolean anPublic = Modifier.isPublic(methodModifier);
            boolean anStatic = Modifier.isStatic(methodModifier);
            allTestMethods.add(geneMethod);
            if (anPublic) {
                if (!anStatic) {
                    geneMethod.invokeMethod = "object";
                    objectMethods.add(geneMethod);
                } else {
                    geneMethod.invokeMethod = "class";
                    classMethods.add(geneMethod);
                }
            } else {
                geneMethod.invokeMethod = "reflection";
                reflectionObjectMethods.add(geneMethod);
            }

        }
    }


}
